package com.liu.hooks;

import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;

import com.liu.util.TrackerLoger;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public class CryptoHook extends AbstractHook{

	public static final String TAG = "#CipherHook#";
	
	public static final String TYPE = "com.liu.hooks.CryptoHook";
	
	public XC_MethodHook cipherInstanceHook = new XC_MethodHook() {
		@Override
		protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
			
			TrackerLoger.log(TAG, "[transformation]" + param.args[0], TYPE, true);
			
		}
	};
	
	public XC_MethodHook cipherInitHook = new XC_MethodHook() {
		
		@Override
		protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
			
			if(param.args.length == 3 
					&& param.args[0] instanceof Integer 
					&& param.args[1] instanceof Key 
					&& param.args[2] instanceof SecureRandom) {
				
				TrackerLoger.log(TAG, "[opmode]" + getOpmode((Integer)param.args[0]), TYPE, true);
				
				((Key)param.args[1]).getFormat();
				
			}
			
			if(param.args.length == 3 
					&& param.args[0] instanceof Integer 
					&& param.args[1] instanceof Certificate 
					&& param.args[2] instanceof SecureRandom) {
				
			}
			
			if(param.args.length == 4
					&& param.args[0] instanceof Integer 
					&& param.args[1] instanceof Key 
					&& param.args[2] instanceof AlgorithmParameterSpec 
					&& param.args[3] instanceof SecureRandom) {
				
			}
			
			if(param.args.length == 4
					&& param.args[0] instanceof Integer 
					&& param.args[1] instanceof Key 
					&& param.args[2] instanceof AlgorithmParameters
					&& param.args[3] instanceof SecureRandom) {
				
			}
			
		}
		
		public String getOpmode(int opmode) {
			
			switch(opmode) {
			case 1:
				return "ENCRYPT_MODE";
			case 2:
				return "DECRYPT_MODE";
			case 3:
				return "WRAP_MODE";
			case 4:
				return "UNWRAP_MODE";
			}
			
			return "Invalid opmode";
		}
		
	};
	
	public XC_MethodHook doFinalHook = new XC_MethodHook() {
		@Override
		protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
			param.setResult(param.args[0]);
			TrackerLoger.log(TAG, "[plainText]" + new String((byte[])param.args[0]), TYPE, true);
			return;
		}
	};
	
	@Override
	public void doHook() {
		XposedBridge.hookAllMethods(Cipher.class, "getInstance", cipherInstanceHook);
		XposedBridge.hookAllMethods(Cipher.class, "init", cipherInitHook);
		XposedHelpers.findAndHookMethod(Cipher.class, "doFinal", "byte[]", doFinalHook);
		//TODO dofinal(),update(),Digest class
	}

	@Override
	public void setClassLoader(ClassLoader classloader) {
		this.classloader = classloader;
		
	}

}
